package com.huantai.common.util.secret;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密解密工具类
 * 
 * @author Ma Chao
 * @version 2018年4月16日 下午2:59:46
 */
public final class AESUtil {
    private AESUtil() {}

    /** 默认加密方式 */
    private static final String DEFAULT_ALGORITHM = "AES";
    /** 默认密钥 */
    private static final String DEFAULT_SECRET_KEY = "ZjphzJphzjPhzjpH";

    // 调用CRM系统加解密
    private static final String PADDING = "AES/CBC/PKCS5Padding";// "算法/模式/补码方式"
    private static final String DEFAULT_ENCODING = "utf-8";
    private static final String IV = "1234567812345678";

    /**
     * 使用默认密钥加密
     */
    public static String encode(String content) throws InvalidKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return new org.apache.commons.codec.binary.Base64().encodeToString(encrypt(
                content.getBytes(DEFAULT_ENCODING), DEFAULT_SECRET_KEY.getBytes(DEFAULT_ENCODING)));
    }

    public static String encode(String content, String key) throws InvalidKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return new org.apache.commons.codec.binary.Base64().encodeToString(
                encrypt(content.getBytes(DEFAULT_ENCODING), key.getBytes(DEFAULT_ENCODING)));
    }

    /**
     * 使用默认密钥解密
     */
    public static String decode(String content) throws InvalidKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return new String(decrypt(content.getBytes(DEFAULT_ENCODING),
                DEFAULT_SECRET_KEY.getBytes(DEFAULT_ENCODING)), DEFAULT_ENCODING);
    }

    public static String decode(String content, String key) throws InvalidKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return new String(
                decrypt(content.getBytes(DEFAULT_ENCODING), key.getBytes(DEFAULT_ENCODING)),
                DEFAULT_ENCODING);
    }

    /**
     * 加密 to CRM
     * 
     * @param code 明文
     * @param key 密钥
     * @return String
     * @throws UnsupportedEncodingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws InvalidAlgorithmParameterException
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public static String encrypt(String code, String key) throws InvalidKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return new org.apache.commons.codec.binary.Base64().encodeToString(
                encrypt(code.getBytes(DEFAULT_ENCODING), key.getBytes(DEFAULT_ENCODING)));

    }

    private static byte[] encrypt(byte[] code, byte[] key)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        SecretKeySpec keySpec = new SecretKeySpec(key, DEFAULT_ALGORITHM);
        Cipher cipher = Cipher.getInstance(PADDING); // NOSONAR // "算法/模式/补码方式"
        // 使用CBC模式，需要一个向量iv，可增加加密算法的强度
        IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
        return cipher.doFinal(code);
    }


    /**
     * 解密 to CRM
     * 
     * @param data 密文
     * @param key 密钥
     * @return String
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws InvalidAlgorithmParameterException
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     */
    public static String decrypt(String data, String key) throws InvalidKeyException,
            UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        return new String(decrypt(data.getBytes(DEFAULT_ENCODING), key.getBytes(DEFAULT_ENCODING)),
                DEFAULT_ENCODING);
    }

    private static byte[] decrypt(byte[] src, byte[] key) throws NoSuchAlgorithmException,
            NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        SecretKeySpec keySpec = new SecretKeySpec(key, DEFAULT_ALGORITHM);
        Cipher cipher = Cipher.getInstance(PADDING);// NOSONAR
        IvParameterSpec iv = new IvParameterSpec(IV.getBytes(DEFAULT_ENCODING));
        cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
        byte[] srcNew = new org.apache.commons.codec.binary.Base64().decode(src);
        return cipher.doFinal(srcNew);
    }
}
